﻿//#define USE_DUNGEONBUDDY_DLL

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using CommonBehaviors.Actions;
using Styx;
using Styx.Common.Helpers;
using Styx.CommonBot;
using Styx.CommonBot.Frames;
using Styx.CommonBot.POI;
using Styx.Helpers;
using Styx.Patchables;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;
#if USE_DUNGEONBUDDY_DLL
using Bots.DungeonBuddyDll;
using Bots.DungeonBuddyDll.Profiles;
using Bots.DungeonBuddyDll.Attributes;
using Bots.DungeonBuddyDll.Helpers;

namespace Bots.DungeonBuddyDll.Dungeon_Scripts.Mists_of_Pandaria
#else
    using Bots.DungeonBuddy.Profiles;
    using Bots.DungeonBuddy.Attributes;
    using Bots.DungeonBuddy.Helpers;
namespace Bots.DungeonBuddy.Dungeon_Scripts.Mists_of_Pandaria
#endif
{
    internal class BrewmoonFestival : Dungeon
    {
        #region Overrides of Dungeon

        public override uint DungeonId
        {
            get { return 539; }
        }

        public override void RemoveTargetsFilter(List<WoWObject> units)
        {
            units.RemoveAll(
                ret =>
                    {
                        var unit = ret.ToUnit();
                        if (unit != null)
                        {
                            if (unit.Entry == DenMotherMoofId && unit.CastingSpellId == TwirlwindId && Me.IsMelee())
                                return true;

                            if (unit.Entry == LiTeId && unit.HasAura("Water Shell") && !Me.IsHealer())
                                return true;
                        }
                        return false;
                    });
        }

        public override void IncludeTargetsFilter(List<WoWObject> incomingunits, HashSet<WoWObject> outgoingunits)
        {
            foreach (var obj in incomingunits)
            {
                var unit = obj as WoWUnit;
                if (unit != null) {}
            }
        }

        public override void WeighTargetsFilter(List<Targeting.TargetPriority> units)
        {
            foreach (var priority in units)
            {
                var unit = priority.Object as WoWUnit;
                if (unit != null) {}
            }
        }

        #endregion

        private const uint HungryVirmenId = 62807;
        private const int TwirlwindId = 124378;
        private const uint DenMotherMoofId = 63518;
        private const uint LiTeId = 63520;
        private readonly WoWPoint _villageCenterLoc = new WoWPoint(1768.085, 341.058, 478.1584);
        private WoWPoint _denMotherSpawnLoc = new WoWPoint(1767.374, 388.2354, 481.6245);

        private static LocalPlayer Me
        {
            get { return StyxWoW.Me; }
        }

        [EncounterHandler(0)]
        public Composite RootEncounter()
        {
            return
                new PrioritySelector(
                    new Decorator(
                        ctx =>
                        ScriptHelpers.IsBossAlive("Karsar the Bloodletter") &&
                        (ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex == 0 && ScriptHelpers.CurrentScenarioInfo.CurrentStage.Criterias[0].IsComplete ||
                         ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex != 0),
                        new Action(ctx => ScriptHelpers.MarkBossAsDead("Karsar the Bloodletter"))),
                    new Decorator(
                        ctx =>
                        ScriptHelpers.IsBossAlive("Den Mother Moof") &&
                        (ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex == 0 && ScriptHelpers.CurrentScenarioInfo.CurrentStage.Criterias[1].IsComplete ||
                         ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex != 0),
                        new Action(ctx => ScriptHelpers.MarkBossAsDead("Den Mother Moof"))),
                    new Decorator(
                        ctx =>
                        ScriptHelpers.IsBossAlive("Li Te") &&
                        (ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex == 0 && ScriptHelpers.CurrentScenarioInfo.CurrentStage.Criterias[2].IsComplete ||
                         ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex != 0),
                        new Action(ctx => ScriptHelpers.MarkBossAsDead("Li Te"))),
                    new Decorator(ctx => ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex == 1, CreateStageTwoBehavior()),
                    new Decorator(
                        ctx => ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex == 2 || ScriptHelpers.CurrentScenarioInfo.CurrentStageIndex == 3,
                        CreateStageThreeAndFourBehavior()));
        }

        [EncounterHandler(63529, "Karsar the Bloodletter")]
        public Composite KarsartheBloodletterEncounter()
        {
            return new PrioritySelector();
        }

        [EncounterHandler(63518, "Den Mother Moof", Mode = CallBehaviorMode.CurrentBoss)]
        public Composite DenMotherMoofSpawnEncounter()
        {
            return new PrioritySelector(
                new Decorator(ctx => ctx == null, ScriptHelpers.CreateClearArea(() => _denMotherSpawnLoc, 50, u => u.Entry == HungryVirmenId)),
                new Decorator(ctx => Me.IsTank() && _denMotherSpawnLoc.Distance(Me.Location) < 10 && Targeting.Instance.IsEmpty(), new ActionAlwaysSucceed()));
        }

        [EncounterHandler(63518, "Den Mother Moof")]
        public Composite DenMotherMoofEncounter()
        {
            AddAvoidObject(ctx => true, () => _denMotherSpawnLoc, 40, 15, u => u.Entry == DenMotherMoofId && u.ToUnit().CastingSpellId == TwirlwindId);
            return new PrioritySelector(new Decorator(ctx => Me.IsTank() && Targeting.Instance.IsEmpty(), new ActionAlwaysSucceed()));
        }

        [EncounterHandler(62793, "Assistant Tart", Mode = CallBehaviorMode.Proximity, BossRange = 40)]
        public Composite AssistantTartEncounter()
        {
            WoWUnit tart = null;
            return new PrioritySelector(
                ctx => tart = ctx as WoWUnit,
                new Decorator(
                    ctx => !Me.HasAura("Water Walking") && Targeting.Instance.IsEmpty() && ScriptHelpers.IsBossAlive("Li Te"), ScriptHelpers.CreateTalkToNpc(() => tart)));
        }

        [EncounterHandler(63520, "Li Te")]
        public Composite LiTeEncounter()
        {
            const uint WaterspoutId = 63823;
            WoWUnit boss = null;
            WoWUnit spout = null;
            AddAvoidObject(ctx => true, 6, u => u.Entry == WaterspoutId && boss != null && boss.IsValid && boss.HasAura("Water Shell"));

            return new PrioritySelector(
                ctx =>
                    {
                        spout = ObjectManager.GetObjectsOfType<WoWUnit>().Where(u => u.Entry == WaterspoutId).OrderBy(u => u.DistanceSqr).FirstOrDefault();
                        return boss = ctx as WoWUnit;
                    },
                new Decorator(ctx => boss.HasAura("Water Shell") && spout != null && spout.Distance > 3, new Action(ctx => Navigator.PlayerMover.MoveTowards(spout.Location))),
                new Decorator(ctx => Me.IsTank() && Targeting.Instance.IsEmpty(), new ActionAlwaysSucceed()));
        }

        [EncounterHandler(64189, "Tian Mistweaver", BossRange = 40, Mode = CallBehaviorMode.Proximity)]
        public Composite TianMistweaverEncounter()
        {
            return
                new PrioritySelector(
                    new Decorator<WoWUnit>(
                        unit => Me.HealthPercent < 60 && unit.HasAura("Mistweaving") && unit.Distance > 4,
                        new Helpers.Action<WoWUnit>(unit => Navigator.GetRunStatusFromMoveResult(Navigator.MoveTo(unit.Location)))));
        }

        private Composite CreateStageTwoBehavior()
        {
            ScenarioStage stage = null;
            const uint krasarangWildBrewId = 63929;
            WoWUnit wildBrew = null;

            return new PrioritySelector(
                ctx =>
                    {
                        wildBrew = ObjectManager.GetObjectsOfType<WoWUnit>().Where(u => u.Entry == krasarangWildBrewId).OrderBy(u => u.DistanceSqr).FirstOrDefault();
                        return stage = ScriptHelpers.CurrentScenarioInfo.CurrentStage;
                    },
                new Decorator(
                    ctx => !stage.Criterias[0].IsComplete || !stage.Criterias[1].IsComplete || !stage.Criterias[2].IsComplete,
                    ScriptHelpers.CreateClearArea(() => _villageCenterLoc, 150)),
                new Decorator(
                    ctx => Lua.GetReturnVal<bool>("return ExtraActionButton1:IsVisible()", 0),
                    new Action(
                        ctx =>
                            {
                                var unit = ScriptHelpers.GetUnfriendlyNpsAtLocation(() => Me.Location, 29).FirstOrDefault();
                                Lua.DoString("ExtraActionButton1:Click()");
                                SpellManager.ClickRemoteLocation(unit != null ? unit.Location : Me.Location);
                                return RunStatus.Failure;
                            })),
                new Decorator(
                    ctx => !stage.Criterias[3].IsComplete && wildBrew != null && Targeting.Instance.IsEmpty() && (Me.IsTank() || wildBrew.Distance <= 35),
                    new PrioritySelector(
                        new Decorator(ctx => wildBrew.WithinInteractRange, new Action(ctx => wildBrew.Interact())),
                        new Decorator(ctx => !wildBrew.WithinInteractRange, new Action(ctx => Navigator.GetRunStatusFromMoveResult(Navigator.MoveTo(wildBrew.Location)))))),
                new Decorator(ctx => Me.IsTank() && Targeting.Instance.IsEmpty(), new ActionAlwaysSucceed()));
        }

        private Composite CreateStageThreeAndFourBehavior()
        {
            return new PrioritySelector(
                ScriptHelpers.CreateClearArea(() => _villageCenterLoc, 150),
                new Decorator(ctx => Me.IsTank() && Targeting.Instance.IsEmpty() && BotPoi.Current.Type == PoiType.None, new ActionAlwaysSucceed()));
        }

        [EncounterHandler(63528, "Warbringer Qobi")]
        public Composite WarbringerQobiEncounter()
        {
            const uint fireLineId = 64266;
            const int fireLineSpellId = 125392;

            WoWUnit boss = null;
            AddAvoidObject(
                ctx => Me.IsRange(),
                4,
                u => u.Entry == fireLineId,
                u => Me.Location.GetNearestPointOnSegment(boss.Location, WoWMathHelper.CalculatePointFrom(u.Location, boss.Location, 40)));

            AddAvoidObject(ctx => Me.IsMelee(), 4, fireLineId);
            return new PrioritySelector(
                ctx => boss = ctx as WoWUnit,
                ScriptHelpers.CreateAvoidUnitAnglesBehavior(ctx => boss.CastingSpellId == fireLineSpellId && boss.Distance < 10, () => boss, new ScriptHelpers.AngleSpan(0, 160)));
        }
    }
}